<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>测试</title>
<style type="text/css">
#code{
	width:500px;
	height:200px;
}
#hint{
	padding:8px;
	border-left:2px solid #ccc;
	background-color:#eee;
	word-wrap:break-word;
	font-size:14px;
	color:#4d4d4d;
	line-height:1.5;
	font-family:consolas;
}
.js-comment{color:#999;font-size:12px;}
.js-reserved{color:#009;font-weight:600;}
.js-native{color:#099;}
.js-client{color:#909;}
.js-string{color:#00f;}
.js-regular{color:#060;}
.js-number{color:#f00;}
</style>
</head>

<body>
<textarea id="code">
var str = "sdf 'sdk lf ";
str += 'vapour';

</textarea>
<button id="btn">format</button>
<div id="hint" style="padding:6px;border-left:2px solid #ccc;background-color:#eee;word-wrap:break-word;"></div>

<script type="text/javascript">
(function(){
	var reg, i,
		elCode = document.getElementById('code'),
		elShow = document.getElementById('hint');
	var keyword = {
		reserved: "break|case|catch|continue|default|delete|do|else|export|function|false|finally|for|if|import|in|item|new|null|return|switch|this|throw|true|try|var|void|while|with",
		native: "abs|acos|Array|asin|atan|atan2|Boolean|ceil|charAt|charCodeAt|concat|cos|Date|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|escape|eval|exp|floor|fromCharCode|Function|getDate|getDay|getFullYear|getHours|getMilliseconds|getMinutes|getMonth|getSeconds|getSelection|getTime|getTimezoneOffset|getUTCDate|getUTCDay|getUTCFullYear|getUTCHours|getUTCMilliseconds|getUTCMinutes|getUTCMonth|getUTCSeconds|getYear|Image|indexOf|isNaN|join|lastIndexOf|log|match|Math|max|min|Number|Object|parse|parseFloat|parseInt|pop|pow|preference|print|push|random|RegExp|replace|reset|resizeBy|resizeTo|reverse|round|search|select|setDate|setFullYear|setHours|setMilliseconds|setInterval|setMinutes|setMonth|setSeconds|setTime|setTimeout|setUTCDate|setUTCFullYear|setUTCHours|setUTCMilliseconds|setUTCMinutes|setUTCMonth|setUTCSeconds|setYear|shift|sin|slice|sort|splice|split|sqrt|String|substr|substring|tan|toGMTString|toLocaleString|toLowerCase|toSource|toString|toUpperCase|toUTCString|typeof|unescape|unshift|unwatch|UTC|valueOf|watch|write|writeln",
		client: "alert|all|anchor|back|big|blink|blur|body|bold|byteToString|captureEvents|clearInterval|clearTimeout|click|close|confirm|disableExternalCapture|document|enableExternalCapture|event|find|fixed|focus|fontcolor|fontsize|forward|getOptionValueCount|getOptionValue|go|handleEvent|home|italics|javaEnabled|link|load|log|mimeTypes|moveAbove|moveBelow|moveBy|moveTo|moveToAbsolute|navigator|open|options|plugins|prompt|refresh|releaseEvents|reload|routeEvent|screen|scroll|scrollBy|scrollTo|small|stop|strike|sub|submit|sup|taintEnabled|unit|window",
		other: "\\(|\\)|\\[|\\]|\\{|\\}"
	}
	document.getElementById('btn').onclick = function(){
		var value = elCode.value;
		var objBuff = [];
		i = 0;
		value = value.replace(/&(\S+?;)/g, '&amp;$1').replace(/</g, '&lt;').replace(/>/g, '&gt;');
		
		/*
			注意这种情况
			//*单行注释
		*/
		value = value.replace(/(.)?(\/\*(?:.|\n)*?\*\/)/gm, function(val, a, b){
			if(a == '/') return val;
			objBuff.push({
				cls: 'js-comment',
				value: b
			});
			return a + '__tmpBuff' + i++ + '__';
		});
		/*
			注意这种情况
			/\/\*(?:.|\n)+?\*\//g
		*/
		value = value.replace(/(.)?(\/\/.*)$/gm, function(val, a, b){
			if(a == '\\') return val;
			objBuff.push({
				cls: 'js-comment',
				value: b
			});
			return a + '__tmpBuff' + i++ + '__';
		});
		
		/*
			正则表达式
		*/
		value = value.replace(/\/.+?[^\\]\/g?m?i?/g, function(val){
			objBuff.push({
				cls: 'js-regular',
				value: val
			});
			return '__tmpBuff' + i++ + '__';
		});
		
		/*
			注意正则表达式中的引号
			/\"vapour\"/
			"vapour\"
		*/
		value = value.replace(/([^\\])?((\"|\').*?([^\\])\3)/g, function(val, a, b){
			objBuff.push({
				cls: 'js-string',
				value: b
			});
			return a + '__tmpBuff' + i++ + '__';
		});
		
		
		
		//数字
		reg=/\b([+-]?(?:\d+(?:\.\d*)?(?:e[+-]?\d+)?|0x[\dA-F]+))\b/gi;
		value= value.replace(reg, function(val){
			return '<span class="js-number">' + val + '</span>';
		});
		
		//关键字
		reg = new RegExp('\\b(' + keyword.client + ')\\b', 'g');
		value = value.replace(reg, '<span class="js-client">$1</span>');
		reg = new RegExp('\\b(' + keyword.native + ')\\b', 'g');
		value = value.replace(reg, '<span class="js-native">$1</span>');
		reg = new RegExp('\\b(' + keyword.reserved + ')\\b', 'g');
		value = value.replace(reg, '<span class="js-reserved">$1</span>');
		
		//运算符
		reg = new RegExp('(' + keyword.other + ')', 'g');
		value = value.replace(reg, '<span class="js-reserved">$1</span>');
		
		value = value.replace(/__tmpBuff(\d+)__/g, function(val, index){
			return '<span class="' + objBuff[index].cls + '">' + objBuff[index].value + '</span>';
		});
		
		value = value.replace(/^\t+/gm, function(val){
			return (new Array(val.length + 1)).join('&nbsp;&nbsp;&nbsp;&nbsp;');
		});
		value = value.replace(/^ +/gm, function(val){
			return (new Array(val.length + 1)).join('&nbsp;');
		});
		
		value = value.replace(/\r?\n/g, function(val){
			return '<br />';
		});
		
		elShow.innerHTML = value;
	}
})();
</script>
</body>
</html>